package com.jay.media.music.ui.play

import android.annotation.SuppressLint
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.media.AudioManager
import android.media.MediaMetadata
import android.media.audiofx.Visualizer
import android.media.session.PlaybackState
import android.util.Log
import android.view.*
import android.widget.SeekBar
import androidx.fragment.app.viewModels
import com.alibaba.android.arouter.launcher.ARouter
import com.bumptech.glide.Glide
import com.bumptech.glide.request.RequestOptions
import com.jay.base.ui.BaseFragment
import com.jay.media.kit.DateUtils
import com.jay.media.kit.LogHelper
import com.jay.media.music.core.provider.METADATA_FAVOR
import com.jay.media.music.core.provider.METADATA_TRACK_SOURCE
import com.jay.media.music.route.RouteConfig
import com.jay.media.music.ui.HomeActivity
import com.jay.media.music.ui.MediaApplication
import com.jay.media.music.ui.R
import com.jay.media.music.ui.databinding.FragmentPlayBinding
import com.jay.media.music.ui.manager.DefaultMusicListener
import com.jay.media.music.ui.manager.MusicClientManager
import jp.wasabeef.glide.transformations.BlurTransformation
import java.lang.Math.abs
import kotlin.math.hypot

/**
 * Create by xuzhou4
 * Date 2021/11/16
 */
class PlayFragment : BaseFragment(), View.OnClickListener {

    companion object {
        const val VOLUME_CHANGED_ACTION = "android.media.VOLUME_CHANGED_ACTION"
    }

    private var _binding: FragmentPlayBinding? = null
    private val binding get() = _binding!!
    private var favorMenu: MenuItem? = null

    private var mVisualizer: Visualizer? = null
    private lateinit var mAudioManager: AudioManager

    private val model: PlayViewModel by viewModels()
    private var mMusicListener = object : DefaultMusicListener() {
        override fun onMetadataChanged(metadata: MediaMetadata?) {
            model.setPlayMusic(metadata)
        }

        override fun onPlaybackStateChanged(state: PlaybackState?) {
            model.setPlayState(state)
        }
    }

    override fun rootView(container: ViewGroup?): View? {
        _binding = FragmentPlayBinding.inflate(layoutInflater)
        return binding.root
    }

    override fun layoutId(): Int = R.layout.fragment_play

    @SuppressLint("RestrictedApi")
    override fun initView(view: View) {
        initToolbar()
        initVolume()
        initPlayView()

        model.getPlayMusic().observe(
            this
        ) { t -> updateMetadata(t) }
        model.getPlayState().observe(
            this
        ) { s -> updatePlaybackState(s) }
        model.setPlayMusic(MusicClientManager.getClient().mMetadata)
        model.setPlayState(MusicClientManager.getClient().mPlaybackState)
    }

    private fun initToolbar() {
        setHasOptionsMenu(true)
        val homeActivity = mActivity as HomeActivity
        homeActivity.setupToolbarNavBar(binding.toolbar, R.drawable.ic_close)
    }

    override fun initData() {
        initVisualizer()
        MusicClientManager.getClient().registerMediaListener(mMusicListener)
    }

    override fun onResume() {
        super.onResume()
        mVisualizer?.enabled = true
    }

    override fun onPause() {
        super.onPause()
        mVisualizer?.enabled = false
    }

    override fun onDestroyView() {
        MusicClientManager.getClient().unregisterMediaListener(mMusicListener)
        MediaApplication.getContext().unregisterReceiver(mVolumeReceiver)
        mVisualizer?.release()
        mVisualizer = null
        super.onDestroyView()
        _binding = null
    }

    private fun initVisualizer() {
        val audioSessionID = MusicClientManager.getClient().mSessionId
        Log.d(TAG, "initData() called : $audioSessionID")
        mVisualizer = Visualizer(audioSessionID)
        mVisualizer?.captureSize = Visualizer.getCaptureSizeRange()[1]
        mVisualizer?.setDataCaptureListener(object : Visualizer.OnDataCaptureListener {
            override fun onWaveFormDataCapture(
                visualizer: Visualizer?,
                waveform: ByteArray?,
                samplingRate: Int
            ) {
//                LogHelper.d(
//                    TAG,
//                    "onWaveFormDataCapture() called with: visualizer = $visualizer, waveform = $waveform, samplingRate = $samplingRate"
//                )
            }

            override fun onFftDataCapture(
                visualizer: Visualizer?,
                fft: ByteArray?,
                samplingRate: Int
            ) {
//                LogHelper.d(
//                    TAG,
//                    "onFftDataCapture() called with: visualizer = $visualizer, fft = $fft, samplingRate = $samplingRate"
//                )

                fft?.apply {
                    val model = FloatArray(fft.size / 2 + 1)
                    model[0] = abs(fft[0].toFloat())
                    model[fft.size / 2] = abs(fft[1].toFloat())
                    for (i in 1 until fft.size / 2) {
                        model[i] = hypot(fft[2 * i].toDouble(), fft[2 * i + 1].toDouble()).toFloat()
                    }

                    //model即为最终用于绘制的数据
                    binding.musicWaveView.updateFFTArray(model)
                }
            }

        }, Visualizer.getMaxCaptureRate() / 2, false, true)
    }

    @SuppressLint("WrongConstant")
    private fun updateMetadata(metadata: MediaMetadata?) {
        metadata?.also {
            binding.toolbar.title = it.getString(MediaMetadata.METADATA_KEY_TITLE)
            binding.toolbar.subtitle = it.getString(MediaMetadata.METADATA_KEY_ARTIST)
            val mediaUri = it.getString(METADATA_TRACK_SOURCE)
            LogHelper.d(TAG, "mediaUri $mediaUri")

            val duration = it.getLong(MediaMetadata.METADATA_KEY_DURATION)
            binding.durationTextview.text = DateUtils.formatMin(duration)
            binding.playSeekbar.max = duration.toInt()

            val favor = it.getString(METADATA_FAVOR)
            LogHelper.d(TAG, "favor $favor")
            favorMenu?.setIcon(if ("true" == favor) R.drawable.ic_favorites_fill else R.drawable.ic_favorites)

            Glide.with(MediaApplication.getContext())
                .load(metadata.getString(MediaMetadata.METADATA_KEY_ALBUM_ART_URI)?.toString())
                .error(R.drawable.ic_music_small)
                .apply(RequestOptions.bitmapTransform(BlurTransformation(10, 6)))
                .into(binding.albumArtView)
        }
    }

    private fun updatePlaybackState(state: PlaybackState?) {
        state?.also {
            binding.playButton.setImageResource(if (it.state == PlaybackState.STATE_PLAYING) R.drawable.pause else R.drawable.play)
            binding.progressTextview.text = DateUtils.formatMin(it.position)
            binding.playSeekbar.progress = it.position.toInt()
        }
    }

    override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
        super.onCreateOptionsMenu(menu, inflater)
        inflater.inflate(
            R.menu.fragment_play,
            menu
        )
        favorMenu = menu.findItem(R.id.action_favor)

        MusicClientManager.getClient().mMetadata?.let {
            val favor = it.getString(METADATA_FAVOR)
            LogHelper.d(TAG, "favor $favor")
            favorMenu?.setIcon(if ("true" == favor) R.drawable.ic_favorites_fill else R.drawable.ic_favorites)
        }
    }

    private fun initVolume() {
        binding.volumeSubButton.setOnClickListener(this)
        binding.volumeAddButton.setOnClickListener(this)

        mAudioManager =
            MediaApplication.getContext().getSystemService(Context.AUDIO_SERVICE) as AudioManager
        val intentFilter = IntentFilter(VOLUME_CHANGED_ACTION)
        MediaApplication.getContext().registerReceiver(mVolumeReceiver, intentFilter)

        binding.volumeSeekbar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
            override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {

            }

            override fun onStartTrackingTouch(seekBar: SeekBar?) {

            }

            override fun onStopTrackingTouch(seekBar: SeekBar?) {

            }
        })

        updateVolume()
    }

    private fun updateVolume() {
        val volume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC)
        val maxVolume = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC)
        binding.volumeSeekbar.max = maxVolume
        binding.volumeSeekbar.progress = volume

        binding.volumeSubButton.setImageResource(
            if (binding.volumeSeekbar.progress == 0) {
                R.drawable.volume_mute
            } else {
                R.drawable.volume_1
            }
        )
    }

    private fun addVolume() {
        mAudioManager.adjustStreamVolume(
            AudioManager.STREAM_MUSIC,
            AudioManager.ADJUST_RAISE,
            AudioManager.FLAG_SHOW_UI
        )
    }

    private fun subVolume() {
        mAudioManager.adjustStreamVolume(
            AudioManager.STREAM_MUSIC,
            AudioManager.ADJUST_LOWER,
            AudioManager.FLAG_SHOW_UI
        )
    }

    private var mVolumeReceiver = object : BroadcastReceiver() {
        override fun onReceive(context: Context?, intent: Intent?) {
            Log.d(TAG, "onReceive() called with: context = $context, intent = $intent")
            if (VOLUME_CHANGED_ACTION == intent?.action) {
                updateVolume()
            }
        }
    }

    private fun initPlayView() {
        binding.prevButton.setOnClickListener(this)
        binding.playButton.setOnClickListener(this)
        binding.nextButton.setOnClickListener(this)
        binding.playSeekbar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
            override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
                if (fromUser) {
                    MusicClientManager.getClient().seekTo(progress)
                }
            }

            override fun onStartTrackingTouch(seekBar: SeekBar?) {
            }

            override fun onStopTrackingTouch(seekBar: SeekBar?) {
            }
        })
    }

    override fun onClick(v: View?) {
        when (v?.id) {
            R.id.volume_add_button -> {
                addVolume()
            }
            R.id.volume_sub_button -> {
                subVolume()
            }
            R.id.play_button -> {
                MusicClientManager.getClient().playOrPause()
            }
            R.id.prev_button -> {
                MusicClientManager.getClient().prev()
            }
            R.id.next_button -> {
                MusicClientManager.getClient().next()
            }
            else -> {
            }
        }
    }

    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        when (item.itemId) {
            R.id.action_favor -> {
                MusicClientManager.getClient().favor()
            }
            R.id.action_eq -> {
                ARouter.getInstance()
                    .build(RouteConfig.SoundEffect.SoundEffect)
                    .withInt(
                        RouteConfig.Param.AudioSessionId,
                        MusicClientManager.getClient().mSessionId
                    )
                    .navigation()
            }
            R.id.action_remove_device -> {
                ARouter.getInstance()
                    .build(RouteConfig.ScreenLock.ScreenLock)
                    .navigation()
            }
            else -> {
            }
        }
        return super.onOptionsItemSelected(item)
    }
}